#include "Sintatico.h"

Sintatico::Sintatico(ListaIdentificadores & mListaLexico, HashIdentificadores &mHashIdentificadores, NoArvore &mNo)
{
	//recebe a lista reconhecida pelo Lexico
	this->mLista = mListaLexico;	
	//recebe a lista de identificadores criada
	this->mHashIdentificadores = &mHashIdentificadores;
	// recebe a arvore criada!!
	this->mArvore = &mNo;
	//nivel lexico e deslocamento inicial e 0
	this->mNivel = 0;
	this->mDeslocamento = 0;
	
}

bool Sintatico::Programa()
{
	this->mArvore->SetTokem("programa"); // seta o n� principal da arvore
	
	if(this->mLista.RetToken() == "program")
	{
		//Insere Arvore
		this->InsereArvore("program", true,mArvore);
		
		
		this->mLista.pop();//retira o program
		if(this->mLista.RetTipo() == 2) //verifico se eh um identificador
		{
			
			//Insere Arvore
			this->InsereArvore(mLista.RetToken(), true,mArvore);
			
			
			this->mLista.pop();//retira o identificador
			
			if(this->mLista.RetToken() == "(")//entre parenteses eh opcional
			{
				this->mLista.pop();// retira a "("
				
				while(this->mLista.RetTipo() == 2)
				{
					
					//Insere Arvore
					this->InsereArvore(mLista.RetToken(), true,mArvore);
					
					this->mLista.pop(); // retira o indentifiador
					
					if(this->mLista.RetToken() == "," && this->mLista.RetNexTipo() == 2)
						this->mLista.pop();
					else
					{
						if(this->mLista.RetToken() == "," && this->mLista.RetNexTipo() != 2)
							cout<<"Esperava ), foi encontrado uma ,."<<endl;
					}
				}
				if(this->mLista.RetToken() == ")")
					this->mLista.pop();
				else
					cout<<"Esperado um ). Nao encontrado."<<endl;
			}
			if(this->mLista.RetToken() == ";")
			{
				this->mLista.pop();
				
				NoArvore *mBloco = InsereArvore("BLOCO",false,mArvore);
				
				Bloco(mBloco);// passa o <bloco> para fun��o Bloco
				
				if(this->mLista.RetToken() == ".")
				{
					this->mLista.pop();
					return true;
				}
				else
					cout<<"Esperava um ..Nao foi encontrado."<<endl;
			}
			else
				cout<<"Esperava um ;. Nao foi encontrado."<<endl;
		}
		else
				cout<<"Esperado um identificador para PROGRAM. Nao encontrado."<<endl;
	}
	else
		cout<<"Esperava palavra reservada PROGRAM, nao encontrada."<<endl;
	return false;
}

void Sintatico::Bloco(NoArvore *mBloco)
{
	Procedimento b;

	while(this->mLista.RetToken() == "var" || this->mLista.RetToken() == "procedure" || this->mLista.RetToken() == "function")
	{
		if(this->mLista.RetToken() == "var")
		{
			this->mDeslocamento = 0;
			//Insere Arvore
			NoArvore *mDeclaraVariavel = InsereArvore("PARTE DECLARACAO VARIAVEIS", false,mBloco);
			
			InsereArvore("var",true,mDeclaraVariavel);
			
			this->mLista.pop();//retiva var
			
			while(this->mLista.RetTipo() == 2)//enquanto tiver identificadores
			{
				//insere na hash
				vector<string> variaveis;
				variaveis.push_back(this->mLista.RetToken());//token das variaveis
				this->mLista.pop();
				//this->InsereHash(0, &b ,mDeclaraVariavel);// passa o bloco para inserir na arvore

				if(this->mLista.RetToken() == ",")
				{
					if(this->mLista.RetNexTipo() != 2)
						cout << "Esperava um :, mas foi encontrado uma ,"<<endl;
					//this->mDeslocamento++;//se tiver mais uma variavel, soma deslocamento
					this->mLista.pop();
				}
					
				if(this->mLista.RetToken() == ":")
				{					
					InsereArvore(":",true,mDeclaraVariavel);								
					
					this->mLista.pop();
					variaveis.push_back(this->mLista.RetToken());//tipo das variaveis
					this->InsereHash(0, variaveis, &b, mDeclaraVariavel);//insere na hash e na arvore as variaveis
					Tipo(mDeclaraVariavel);
					
					if(this->mLista.RetToken() == ";")
						this->mLista.pop();
					else
						cout << "Esperado um ;, nao encontrado."<<endl;
				}
				else
				{
					if(this->mLista.RetTipo() != 2)
						cout << "Esperado um :, nao encontrado"<<endl;
				}
			}
			
		}
		
		
		if(this->mLista.RetToken() == "procedure")
		{
			this->mNivel++;//soma um nivel
			
			this->mLista.pop();//retira o "procedure"
			
			if(this->mLista.RetTipo() == 2)//se eh um identificador
			{
				//this->mLista.pop();
				
				NoArvore *mProcedimento = InsereArvore("PARTE DECLARACAO PROCEDIMENTO",false,mBloco);
				
				this->InsereHash(1,&b,mProcedimento);// insere na hash
				
			}
			else
				cout<<"Esperado um identificador para PROCEDURE. Nao encontrado"<<endl;

			this->mNivel--;
		}
		
		if(this->mLista.RetToken() == "function")
		{
			this->mNivel++;
			this->mLista.pop();//retira function
			if(this->mLista.RetTipo() == 2)//se eh um identificador
			{
				//this->mLista.pop();//
				NoArvore *mFuncao = InsereArvore("PARTE DECLARACAO FUNCAO",false,mBloco);
				
				this->InsereHash(3 , &b,mFuncao);
				
			}
			else
				cout<<"Esperado um identificador para FUNCTION. Nao encontrado"<<endl;
			this->mNivel--;			
		}
	}
	
	NoArvore *mComandoComposto = InsereArvore("COMANDO COMPOSTO",false,mBloco);
	
	ComandoComposto(mComandoComposto);
	
}


// parametros formais com sobrecarga
void Sintatico::Tipo(NoArvore* mTipo)
{
	
	if(this->mLista.RetTipo() == 2 || this->mLista.RetTipo() == 1)//se for um identificador
	{
		InsereArvore(this->mLista.RetToken(),true,mTipo);
		this->mLista.pop();
	}
	else
		cout<<"Esperado um identificador valido para o tipo. Nao encontrado."<<endl;	
}

void Sintatico::ParametrosFormais(Procedimento *mProcedure, NoArvore *mParamFormal)
{//MUDAR PARA ALTERAR A INSERCAO POR VECTOR
	if(this->mLista.RetToken() == "(")
	{
		this->mLista.pop();//retira o "("
		this->mPassagem = 0;//inicialmente a passagem eh por copia
		this->mDeslocamento = -3;
		
		while(this->mLista.RetToken() != ")")
		{
			if(this->mLista.RetToken() == "var")
			{
				this->mPassagem = 1;//se achei um var, passagem por referencia
				this->mLista.pop();//retira o "var"
			}
			
			InsereArvore("[var]",true,mParamFormal);	
		
			if(this->mLista.RetTipo() != 2)
				cout<<"Esperado um identificador, nao encontrado."<<endl;
			vector<string> variaveis;
			while(this->mLista.RetTipo() == 2)
			{
				
				//this->mLista.pop();//retira o indetificador
				mProcedure->SetNumParametros();
				//mParamFormal � o n� da arvore do procedimento
				
				//insere na hash
				
				variaveis.push_back(this->mLista.RetToken());//token das variaveis
				this->mLista.pop();
					
//				this->InsereHash(2, mProcedure, mParamFormal); // insere na hash para para. FORMAL!
				
				
				if(this->mLista.RetToken() == "," && this->mLista.RetNexTipo() == 2)
				{
					this->mLista.pop();
					this->mDeslocamento--;
				}
				else
				{
					if(this->mLista.RetToken() == "," && this->mLista.RetNexTipo() != 2)
						cout<<"Esperado um :, encontrada uma ,"<<endl;
				}
			}
			
			//verifico a variavel flag, pois so devo entrar aqui se tiver achado um identificador logo apos o (
			if(this->mLista.RetToken() == ":")
			{
				InsereArvore(":",true,mParamFormal);
				
				this->mLista.pop();//retira ":"
				
				if(this->mLista.RetTipo() == 2 ||this->mLista.RetTipo() == 1 )
				{
					InsereArvore(this->mLista.RetToken(),true,mParamFormal);
					variaveis.push_back(this->mLista.RetToken());//insere o tipo das variaveis no fim do vector
					this->InsereHash(2, variaveis, mProcedure, mParamFormal);//insere o conjunto de variaveis na hash
					
					this->mLista.pop();//retira o identificador
					if(this->mLista.RetToken() == ";")
					{
						this->mPassagem = 0;//retorno a passagem para copia
						this->mLista.pop();
					}
				}
				else
					cout<<"Esperado um identificador valido. Nao encontrado"<<endl;
			}
			else
				cout<<"Esperava um :, nao encontrado."<<endl;			
		}
		this->mLista.pop();
	}
	else
		cout<<"Esperado um (, nao encontrado."<<endl;	
}

//recebe o N� de arvore do bloco!!

void Sintatico::ParametrosFormais()
{
	
	
	if(this->mLista.RetToken() == "(")
	{
		this->mLista.pop();
		while(this->mLista.RetToken() != ")")
		{
			if(this->mLista.RetToken() == "var")
				this->mLista.pop();
			
			while(this->mLista.RetTipo() == 2)
			{
				this->mLista.pop();
				if(this->mLista.RetToken() == "," && this->mLista.RetNexTipo() == 2)
					this->mLista.pop();
			}
			
			if(this->mLista.RetToken() == ":")
			{
				this->mLista.pop();
				if(this->mLista.RetTipo() == 2)
				{
					this->mLista.pop();
					if(this->mLista.RetToken() == ";")
						this->mLista.pop();
				}
			}			
		}
		this->mLista.pop();
		
	}

}
//sobrecarga 
void Sintatico::Comando(NoArvore* mComando)
{
	if(this->mLista.RetNexTipo() == 3) //se eu tenho um numero
	{
		InsereArvore(this->mLista.RetToken(),true,mComando);
	
		this->mLista.pop();
		if(this->mLista.RetToken() == ":")
		{
			InsereArvore(":",true,mComando);
			this->mLista.pop();
		}
		else
			cout<<"Esperava um :. Nao encontrado."<<endl;
	}
	NoArvore *mComandoSemRotulo = InsereArvore("COMANDO SEM ROTULO",false,mComando);
		
	ComandoSemRotulo(mComandoSemRotulo);
}

void Sintatico::ComandoSemRotulo(NoArvore* mComandoSemRotulo)
{
	/** indetificador entre "(" ")"
	 *  identificador simples
	 * "goto"
	 * "begin"
	 * "if"
	 * "while"
	 */
	 int mTipoCorrente  = mLista.RetTipo(); 
	
	 // um identificador valido
	
	 switch (mTipoCorrente)
	 {
	 	
	 	case 2:
	 	{
	 		if(mLista.RetNexToken() == ":=")
	 		{
	 			NoArvore *mAtribuicao = this->InsereArvore("ATRIBUICAO",false,mComandoSemRotulo);
	 			
	 			this->InsereArvore(this->mLista.RetToken(),true,mAtribuicao);
	 		
				mLista.pop(); // retira o identificador
				this->InsereArvore(":=",true,mAtribuicao);
				
				mLista.pop();//retira o identificador
				NoArvore *mExpressao = this->InsereArvore("EXPRESSAO",false,mAtribuicao);
				
	 			Expressao(mExpressao); //expressao passaro 
	 			break;
	 		}
	 		
	 		//ARVORE
			NoArvore *mExEntreParenteses = InsereArvore("EXPRESSAO ENTRE PARENTESES",false,mComandoSemRotulo);
			InsereArvore(this->mLista.RetToken(),true,mExEntreParenteses);	
			
			this->ExEntreParenteses(mExEntreParenteses);
	 		break;
	 	}
	 	case 1:
	 	{
	 		if(mLista.RetToken()== "begin")
	 		{
	 			ComandoComposto(mComandoSemRotulo);//comando composto passaro
	 			break;
	 		}
	 		if(mLista.RetToken()== "if")
	 		{
	 				//ARVORE
	 				NoArvore *mCondicional = this->InsereArvore("COMANDO CONDICIONAL",false,mComandoSemRotulo);
	 				this->InsereArvore("if",true,mCondicional);
	 				mLista.pop(); // retira o "if"
	 				
	 				NoArvore *mExpressao = this->InsereArvore("EXPRESSAO",false,mCondicional);
	 				Expressao(mExpressao); // chama a fun��o do passaro
					
	 				if(mLista.RetToken() =="then")
	 				{
	 					//ARVORE
	 					this->InsereArvore("then",true,mCondicional);
	 					mLista.pop(); //retira o then
	 					
	 					//ARVORE
	 					NoArvore *mComandoSemRotulo = this->InsereArvore("COMANDO SEM ROTULO",false,mCondicional);
	 					ComandoSemRotulo(mComandoSemRotulo);
	 					
	 					//"else"  opcional
	 					if(!mLista.Empty() && mLista.RetToken() =="else")
	 					{
	 						//ARVORE
	 						this->InsereArvore("else",true,mCondicional);
	 						mLista.pop(); //retira o else
	 					
	 						//ARVORE
	 						NoArvore *mComandoSemRotulo = this->InsereArvore("COMANDO SEM ROTULO",false,mCondicional);
	 						ComandoSemRotulo(mComandoSemRotulo);
	 					}
	 						 					
	 				}
	 				else
	 					cout<<"Esperado um THEN. Nao encontrado."<<endl;
	 				break;
	 			}
	 			if(mLista.RetToken()== "while")
	 			{
	 				
	 				//ARVORE
	 				NoArvore *mRepetitivo = this->InsereArvore("COMANDO REPETITIVO",false,mComandoSemRotulo);
	 				this->InsereArvore("while",true,mRepetitivo);
	 				mLista.pop(); // retira o "while"
	 				
	 				NoArvore *mExpressao = this->InsereArvore("EXPRESSAO",false,mRepetitivo);
	 				Expressao(mExpressao); // chama a fun��o do passaro
					
	 				 				
					if(mLista.RetToken() =="do")
	 				{
	 					//arvore
	 					this->InsereArvore("do",true,mRepetitivo);
	 					NoArvore *mSemRotulo = this->InsereArvore("COMANDO REPETITIVO",false,mRepetitivo);
	 					
	 					mLista.pop();//retira "do"
	 					
	 					ComandoSemRotulo(mSemRotulo);
	 					
	 				}
	 				else
	 					cout<<"Esperado um DO. Nao encontrado."<<endl; 
	 				break;				
	 			}
	 			if(mLista.RetToken() == "read")
	 			{
	 				
	 				//ARVORE
	 				NoArvore *mRead = this->InsereArvore("COMANDO READ",false,mComandoSemRotulo);
	 				this->InsereArvore("read",true,mRead);
	 					 				
	 				mLista.pop();//retira o "read"
	 				if(mLista.RetToken() == "(")
	 				{
	 					this->InsereArvore("(",true,mRead);
	 					
	 					mLista.pop();//retira o "("
	 					
	 					while(this->mLista.RetTipo() == 2)//se eu tiver um idenficador
	 					{
	 						//ARVORE
	 						this->InsereArvore(this->mLista.RetToken(),true,mRead);
	 						this->mLista.pop();
	 						
	 						if(this->mLista.RetToken() == "," && this->mLista.RetNexTipo() == 2)
	 						{
	 							this->InsereArvore(",",true,mRead);
	 							this->mLista.pop();//retiro a virgula
	 						}
	 						else
	 						{
	 							if(this->mLista.RetToken() == "," && this->mLista.RetNexTipo() != 2)
	 								cout<<"Esperado um ). Encontrada uma ,."<<endl;
	 						}
	 					}
	 					
	 					if(this->mLista.RetToken() != ")")
	 						cout<<"Esperado um ). Nao encontrado."<<endl;
 						else
 						{
		 					this->InsereArvore(")",true,mRead);
		 					mLista.pop(); // retira o ")"
		 					break;
 						}
	 				}
	 				else
	 					cout<<"Esperado um (. Nao encontrado."<<endl;
	 			}
	 			if(mLista.RetToken() == "write")
	 			{
	 				
	 				//ARVORE
	 				NoArvore *mWrite = this->InsereArvore("COMANDO WRITE",false,mComandoSemRotulo);
	 				this->InsereArvore("write",true,mWrite);
	 				
	 					
	 				
	 				mLista.pop();//retira o "write"
	 				if(mLista.RetToken() == "(")
	 				{
	 					//ARVORE
	 					this->InsereArvore("(",true,mWrite);
	 					mLista.pop();//retira o "("
	 					
	 					//ARVORE
	 					NoArvore *mExpressao = this->InsereArvore("EXPRESSAO",false,mWrite);
	 					Expressao(mExpressao); //expressao passarinho
	 					while(mLista.RetToken() == ",")
	 					{
	 						    this->InsereArvore(",",true,mWrite);
	 							mLista.pop(); //retiro retiro ","
	 							//Expressao(); //expressao passarinho
	 					}
	 					
	 					if(this->mLista.RetToken() != ")")
	 						cout<<"Esperado um ). Nao encontrado."<<endl;
 						else
 						{
		 					this->InsereArvore(")",true,mWrite);
		 					mLista.pop(); // retira o ")"
		 					break;
 						}
	 				}
	 				else
	 					cout<<"Esperado um (. Nao encontado."<<endl;
	 			}
			}
		}
}

void Sintatico::Expressao(NoArvore* mExpressao)
{
	NoArvore *mExpressaoSimples = InsereArvore("EXPRESSAO SIMPLES",false,mExpressao);
		
	
	ExpressaoSimples(mExpressaoSimples);
	
	if(this->mLista.RetToken() == "=" || this->mLista.RetToken() == "<>" || this->mLista.RetToken() == "<" || this->mLista.RetToken() == "<=" || this->mLista.RetToken() == ">=" || this->mLista.RetToken() == ">")
	{
		NoArvore *mRelacao = InsereArvore("RELACAO",false,mExpressao);
		
		InsereArvore(this->mLista.RetToken(),true,mRelacao);
		
		this->mLista.pop();
		
		NoArvore *mExpressaoSimples = InsereArvore("EXPRESSAO SIMPLES",false,mExpressao);
		
		ExpressaoSimples(mExpressaoSimples);
	}
	
}

void Sintatico::ExpressaoSimples(NoArvore* mExpressaoSimples)
{
	// tratar quando nao � nem + ou -
	if( mLista.RetToken() == "+" || mLista.RetToken() == "-" )
	{
		InsereArvore(this->mLista.RetToken(),true,mExpressaoSimples);
		
		mLista.pop(); // retira o operador
	}
	NoArvore *mTermo = InsereArvore("TERMO",false,mExpressaoSimples);
	
	Termo(mTermo);			
		
		
	//proximo passo para verificar expressao  simples
	//"+" "-" "or"
	while( mLista.RetToken() == "+" || mLista.RetToken() == "-" || mLista.RetToken() == "or" ) 
	{
		// INSERE ARVORE
		this->InsereArvore(mLista.RetToken(),true,mExpressaoSimples);
		
		mLista.pop();
		
		// INSERE ARVORE
		NoArvore * mTermo = this->InsereArvore("TERMO",false,mExpressaoSimples);
	
		Termo(mTermo);
		
	}
	
	
}


void  Sintatico::Termo(NoArvore * mTermo)
{
	//ARVORE
	NoArvore * mFator = this->InsereArvore("FATOR",false,mTermo);
	
	//trata o fator
	Fator(mFator);
	
	//proximo passo para verificar termo
	//"+" "-" "or"
	
	while( mLista.RetToken() == "*" || mLista.RetToken() == "div" || mLista.RetToken() == "and" ) 
	{
		//ARVORE
		this->InsereArvore(mLista.RetToken(),true,mTermo);
		
		mLista.pop();
		
		//ARVORE
		NoArvore * mFator = this->InsereArvore("FATOR",false,mTermo);
		Fator(mFator);
	}
		
}

//calcula expressao entre parenteses
void Sintatico::Fator(NoArvore * mFator)
{
	
		// variavel | numero | chamada de funcao | ( expressao) | not fator
	
	// retorna o tipo do identificador na lista
	int mTipoCorrente  = mLista.RetTipo(); 
	
	// um identificador valido
	
	switch (mTipoCorrente)
	{
		case  2://identificador
		{
			
			if ( mLista.RetToken() == "not" )
			{
				//ARVORE
				InsereArvore("not",true,mFator);
				//ARVORE
				NoArvore *mFator1 = InsereArvore("FATOR",false,mFator);
				
				mLista.pop(); // retira o "not"
				
				this->Fator(mFator1);
				
				break;
			}
			if(this->mLista.RetNexToken() == "(")
			{	
				//ARVORE
				NoArvore *mExEntreParenteses = InsereArvore("EXPRESSAO ENTRE PARENTESES",false,mFator);
				InsereArvore(this->mLista.RetToken(),true,mExEntreParenteses);
				
				ExEntreParenteses(mExEntreParenteses);//identificador ( expressao)
			}
			else
			{
				NoArvore *mVariavel = InsereArvore("VARIAVEL",false,mFator);
				InsereArvore(this->mLista.RetToken(),true,mVariavel);
				this->mLista.pop();// retira o identificador
			}
				
			break;
		}
		case 3:
		{
			NoArvore *mNumero = InsereArvore("NUMERO",false,mFator);
							
			this->Numero(mNumero);
			
			break;			
		}
		case 4:
		{
			if(mLista.RetToken() == "(")
			{	
				
				InsereArvore("(",true,mFator);
				NoArvore * mExpressao = this->InsereArvore("EXPRESSAO",false,mFator);
				InsereArvore(")",true,mFator);
												
				mLista.pop();//verifica "("
				Expressao(mExpressao);// expressa� passaro
				
				if(this->mLista.RetToken() != ")")
					cout<<"Esperado um ). Nao encontrado."<<endl;
				else				
					mLista.pop();//retira ")"

			}
			else
				cout<<"Esperado um (. Nao encontrado."<<endl;
			break;
			
		}
	}
	
}
void Sintatico::Numero(NoArvore * mNumero)
{
	if( mLista.RetTipo() == 3)
	{
		InsereArvore(this->mLista.RetToken(),true, mNumero);
		mLista.pop();
	}
	else
		cout<<"Esperado um digito numerico. Nao encontrado"<<endl;
}
void  Sintatico::ExEntreParenteses(NoArvore *mExEntreParenteses)
{		
	mLista.pop();//reita o identificador
		
	if ( mLista.RetToken() == "(") 
	{	
		//ARVORE
		InsereArvore("(",true,mExEntreParenteses);
		NoArvore * mExpressao = this->InsereArvore("EXPRESSAO",false,mExEntreParenteses);
		
		mLista.pop();//verificar "("
		
		Expressao(mExpressao); 
			
		while( mLista.RetToken() == "," )
		{	
			NoArvore * mExpressao = this->InsereArvore("EXPRESSAO",false,mExEntreParenteses);
			
			//trata expressao com funcao passarinho
			mLista.pop();//verificar ","
			Expressao(mExpressao);//expressao passaro 					      
		}
			
		if( mLista.RetToken() == ")" )
		{
			//ARVORE
			InsereArvore(")",true,mExEntreParenteses);
			//reita o caracter da lista
			mLista.pop(); // verificarar ")"
		}
		else
			cout<<"Esperado um ). Nao encontrado."<<endl;
	}
	else
		cout<<"Esperado um (. Nao encontrado."<<endl;
}

void Sintatico::ComandoComposto(NoArvore* mComandoComposto)
{
	if(this->mLista.RetToken() == "begin")
	{
		NoArvore *mAtribuicao = this->InsereArvore("begin",true,mComandoComposto);
		this->mLista.pop();
		while(this->mLista.RetToken() != "end")
		{
			NoArvore *mComando = this->InsereArvore("COMANDO",false,mComandoComposto);
		
			Comando(mComando);
			
			if(this->mLista.RetToken() == ";")
			{
				this->InsereArvore(";",true,mComandoComposto);
				this->mLista.pop();
			}
			else
			{
				if(this->mLista.RetToken() != "end" && this->mLista.RetToken() != ";")
					cout<<"Esperado um ;, nao encontrado."<<endl;
			}
		}
		this->InsereArvore("end",true,mComandoComposto);
		this->mLista.pop();//RETIRA O "END"
	}
	else
		cout<<"Esperado um BEGIN. Nao encontrado."<<endl;
}

void Sintatico::InsereHash(int escolha, vector<string> & variaveisDeclaradas, Procedimento * Proc, NoArvore* mDeclaraVariavel)
{
	//variaveis sao do tipo 0
	this->mDeslocamento = 0;
	VariavelSimples *variavel = new VariavelSimples;
	if(escolha == 2)
	{
		variavel->IsFormal();
		variavel->SetPassagem(this->mPassagem);
		cout<<"Passagem por "<<this->mPassagem<<endl;
		this->mDeslocamento = -3;
	}
	int tipo;
	if(variaveisDeclaradas.back() == "integer")//retiro o tipo das variaveis do inicio do vetor
		tipo = 0;//seto o tipo para inteiro
	else
		tipo = 1;//seto o tipo para boolean
	variaveisDeclaradas.pop_back();
	
	for(int cont = 0; cont < variaveisDeclaradas.size(); cont++)
	{
		//nomeia a varaivel, passando nome da ultima inserida
		variavel->SetId(variaveisDeclaradas.back());
		//variavel simples
		variavel->SetCategoria(0);
		//nivel onde se encontra
		variavel->SetNivel(this->mNivel);
		//para setar o deslocamento verifico se eh parametro formal
		if(escolha == 2)
		{
			if(cont > 0)
				this->mDeslocamento--;
		}
		else
		{
			if(cont == 0)
				this->mDeslocamento = variaveisDeclaradas.size();
			else if(cont > 0)
				this->mDeslocamento--;
		}
		variavel->SetDeslocamento(this->mDeslocamento);
		variavel->SetTipo(tipo);
		cout<<"Nivel, Deslocamento"<<this->mNivel<<","<<this->mDeslocamento<<endl;
		if(!this->mHashIdentificadores->PesquisaVariavelNivel(variavel));
		{
			//se nao encontrar a palavra no nivel insere na hash de identificadores
			this->mHashIdentificadores->Add(variavel);
		}

		InsereArvore(variaveisDeclaradas.back(),true,mDeclaraVariavel,variavel);
		variaveisDeclaradas.pop_back();		
		
		if(escolha == 2)
		{	
			Proc->InsereParamentro(variavel);
		}
	}
	
}


void Sintatico::InsereHash(int escolha , Procedimento * Proc, NoArvore* mDeclaraVariavel)
{
		
		if(escolha == 0 || escolha == 2 )
		{
			
			//deve-se criar um N� de hash tipo identificador
			VariavelSimples *variavel = new VariavelSimples;
			
			if(escolha == 2)
			{
				variavel->IsFormal();
				variavel->SetPassagem(this->mPassagem);
				cout<<"Passagem por "<<this->mPassagem<<endl;
			}
			
			
			//nomeia a variavel
			variavel->SetId(this->mLista.RetToken()); 
			//categoria de variavel simples
			variavel->SetCategoria(0);
			//nivel onde se encontra
			variavel->SetNivel(this->mNivel);
			//deslocamento da variavel
			variavel->SetDeslocamento(this->mDeslocamento);
			//tipo da variavel "0" == INTEGER!!  ARRUMAR
			variavel->SetTipo(0);
			cout<<"Nivel, Deslocamento"<<this->mNivel<<","<<this->mDeslocamento<<endl;
			//variavel->Ret();
			if(!this->mHashIdentificadores->PesquisaVariavelNivel(variavel));
			{
				//se nao encontrar a palavra no nivel insere na hash de identificadores
				this->mHashIdentificadores->Add(variavel);
			}
			
			InsereArvore(this->mLista.RetToken(),true,mDeclaraVariavel,variavel);
			
			
			
			if(escolha == 2)
			{	
				Proc->InsereParamentro(variavel);
			}
			
			mLista.pop(); // retira o identificador
			
		}
		else
		{
			if(escolha == 1 || escolha == 3)
			{
				Procedimento *mProcedure = new Procedimento;
				mProcedure->SetId(this->mLista.RetToken());
				mProcedure->SetNivel(this->mNivel);//nivel do procedimento
				mProcedure->SetPassagem(0);//referencia mudar
				//mProcedure.SetNumParametros(0);//ver isso
				
				
				
				if (escolha == 1)
				{
					mProcedure->SetCategoria(1);// procediemento categoria 1
					
					InsereArvore("procedure",true,mDeclaraVariavel);
					
					InsereArvore(this->mLista.RetToken(),true,mDeclaraVariavel,mProcedure);
					
					mLista.pop();// retia o indentificador	
					
					if(this->mLista.RetToken() == "(")
					{
						NoArvore *mParamProcedure = InsereArvore("PARAMETROS FORMAIS",false,mDeclaraVariavel);
						
						
						// passa o n� parametrod de procedimento
						ParametrosFormais(mProcedure,mParamProcedure);
					}
					if(this->mLista.RetToken() == ";")
					{
						InsereArvore(";",true,mDeclaraVariavel);
						
						
						NoArvore *mPocedureBloco = InsereArvore("BLOCO",false,mDeclaraVariavel);
						
												
						
						this->mLista.pop();//retira o ";"
						
						Bloco(mPocedureBloco);
						
						if(this->mLista.RetToken() == ";")
							this->mLista.pop();
					}
					// insere o procedimento na hash
					this->mHashIdentificadores->Add(mProcedure);
					
				}
				else // no caso de ser funcao
				{
					mProcedure->SetCategoria(2);// function categoria 2
					
					NoArvore *mFunction = InsereArvore("function",true,mDeclaraVariavel);
					
					
					InsereArvore(this->mLista.RetToken(),true,mDeclaraVariavel,mProcedure);
					
					this->mLista.pop();//retiro o identificador da funcao
										
					if(this->mLista.RetToken() == "(")
					{
						NoArvore *mParamFunction = InsereArvore("PARAMETROS FORMAIS",false,mDeclaraVariavel);
									
						ParametrosFormais(mProcedure,mParamFunction);
						
					}
					if(this->mLista.RetToken() == ":")
					{
						InsereArvore(":",true,mDeclaraVariavel);

						this->mLista.pop();

						if(this->mLista.RetTipo() == 1 || this->mLista.RetTipo() == 2)//palavra reservada integer ou boolean
						{
							
							// tipo do parametro
							mProcedure->SetTipoFuncao(0); //verificar
							InsereArvore(this->mLista.RetToken(),false,mDeclaraVariavel);
							
							cout<<"AQUI "<<this->mLista.RetToken()<<endl;
							this->mLista.pop();//retira o identificador
							
							if(this->mLista.RetToken() == ";")
							{
								InsereArvore(";",true,mDeclaraVariavel);
								
								NoArvore *mPocedureBloco = InsereArvore("BLOCO",false,mDeclaraVariavel);
										
								this->mLista.pop();	//retira p ";"			
												
								Bloco(mPocedureBloco);
								
								if(this->mLista.RetToken() == ";")
									this->mLista.pop();
							}
						}
					}
					
					this->mHashIdentificadores->Add(mProcedure);	
				}
			
			}
		}
			
}
NoArvore* Sintatico::InsereArvore(string mNome, bool mTerminal, NoArvore* mPai)
{
	// INSERE ARVORE
	NoArvore *mFilho = new NoArvore;// cria um novo n�
	
	mFilho->SetTokem(mNome); // seta o tokem
	
	if(mTerminal)
		mFilho->SetTerminal();// � terminal
	mPai->InsereFilho(mFilho);// insere program na arvore pai (n� principal
		
	return mFilho;
}


NoArvore * Sintatico::InsereArvore(string mNome, bool Terminal, NoArvore * mPai,NoHash * mPonteiroHash)
{
	NoArvore *mFilho = new NoArvore;// cria um novo n�
	mFilho->SetTokem(mNome); // seta o tokem
	mFilho->InsereVar(mPonteiroHash); //aponta para variavel na hash
	mFilho->SetTerminal(); // � um terminal
	mPai->InsereFilho(mFilho);// insere na arvore pai
	return mFilho; 
}

void Sintatico::MostraArvore()
{
	//realizo uma impressao em nivel a partir da raiz
	unsigned int cont;
	queue<NoArvore*> fila;
	queue<int> qtd;
	vector<NoArvore*> filhos;
	
	NoArvore* raiz = mArvore;
	
	fila.push(raiz);
	int f = 1;
	int printed = 0;
	qtd.push(f);
	
	while(!fila.empty())
	{
		//copio o primeiro da fila e retiro
		NoArvore* no = fila.front();
		fila.pop();
		no->mostra();
		printed++;
		cout<<" ";
		if(printed == qtd.front())
		{
			printed = 0;
			qtd.pop();
			cout<<endl;
		}
		filhos = no->GetFilhos();
		f = 0;
		bool son = false;
		for(cont = 0; cont < filhos.size(); cont++)
		{
			son = true;
			fila.push(filhos[cont]);
			f++;
		}
		if(son)
			qtd.push(f);
	}
}

Sintatico::~Sintatico()
{
}
